import 'package:flutter/material.dart';
import 'package:todos_app_core/todos_app_core.dart';
import 'package:todos_repository_core/todos_repository_core.dart';
import 'package:todos_repository_local_storage/todos_repository_local_storage.dart';
import './models.dart';

enum VisibilityFilter { all, active, completed }

class TodoListModel extends ChangeNotifier {
  final TodosRepository repository;
  VisibilityFilter _filter;
  List<Todo> _todos;
  bool _isLoading = false;
  TodoListModel({
    required this.repository,
    List<Todo> todos = const [],
    VisibilityFilter filter = VisibilityFilter.all,
  }) : _filter = filter,
       _todos = List.from(todos);

  VisibilityFilter get filter => _filter;
  set filter(VisibilityFilter filter) {
    _filter = filter;
    notifyListeners();
  }

  int get numCompleted => _todos.where((todo) => todo.complete).length;
  int get numActive => _todos.where((todo) => !todo.complete).length;

  Future<void> loadTodos() {
    _isLoading = true;
    notifyListeners();
    return repository
        .loadTodos()
        .then((loadTodos) {
          // final loadTodoList = loadTodos.map(Todo.fromEntity);
          // _todos = [..._todos, ...loadTodoList.toList()];
          _todos.addAll(loadTodos.map(Todo.fromEntity));
          _isLoading = false;
          notifyListeners();
        })
        .catchError((err) {
          _isLoading = false;
          notifyListeners();
        });
  }

  void updateTodo(Todo todo) {
    Todo oldTodo = _todos.firstWhere((t) => t.id == todo.id);
    var replaceIndex = _todos.indexOf(oldTodo);
    _todos.replaceRange(replaceIndex, replaceIndex + 1, [todo]);
    notifyListeners();
  }

  bool get isLoading => _isLoading;
  List<Todo> get filteredTodos {
    // return _todos;
    return _todos.where((todo) {
      switch (_filter) {
        case VisibilityFilter.all:
          return true;
        case VisibilityFilter.active:
          return !todo.complete;
        case VisibilityFilter.completed:
          return todo.complete;
      }
    }).toList();
  }

  void addTodo(Todo todo) {
    _todos.add(todo);
    notifyListeners();
  }

  void clearCompleted() {
    _todos.removeWhere((todo) => todo.complete);
    notifyListeners();
  }

  void toggleAll() {
    bool allComp = _todos.every((todo) => todo.complete);
    _todos = _todos.map((todo) {
      return todo.copy(complete: !allComp);
    }).toList();
    notifyListeners();
  }
}
